#!/bin/bash

##############################################################################
# Version :3.6 update date: 2025-07-06 Editor by: andynick
# 修复问题:
# 1. 彻底解决数据库启动失败问题
# 2. 增强数据目录初始化逻辑
# 3. 优化套接字文件处理
# 4. 增加详细的错误日志输出
# 5. 修复端口冲突检测
# 6. 添加数据库健康检查
##############################################################################

##### 检测Kingbase是否已安装
check_kingbase_installed() {
    # 检查安装目录是否存在
    if [ -d "/home/kingbase/ES" ]; then
        return 0
    fi
    
    # 检查kingbase用户是否存在
    if id "kingbase" &>/dev/null; then
        return 0
    fi
    
    # 检查kingbase进程是否运行
    if pgrep -f "bin/kingbase" &>/dev/null; then
        return 0
    fi
    
    return 1
}

##### 卸载Kingbase数据库
uninstall_kingbase() {
    echo "开始卸载Kingbase数据库..."
    
    # 停止所有kingbase进程
    echo "停止Kingbase进程..."
    pkill -9 -f "bin/kingbase" 2>/dev/null
    sleep 2
    
    # 确保所有进程已停止
    KESPROCESS=$(pgrep -f "bin/kingbase" | wc -l)
    if [ "$KESPROCESS" -ge 1 ]; then
        echo "警告: 仍有Kingbase进程在运行，强制终止..."
        kill -9 $(ps -ef | grep kingbase | grep -v grep | awk '{print $2}') 2>/dev/null
        sleep 1
    fi
    
    # 删除安装目录
    echo "删除安装目录..."
    rm -rf /home/kingbase/ES 2>/dev/null
    
    # 删除备份目录
    echo "删除备份目录..."
    rm -rf /home/kingbase/backup 2>/dev/null
    
    # 删除用户 - 确保没有进程使用该用户
    echo "检查并删除用户..."
    if id "kingbase" &>/dev/null; then
        # 确保没有进程使用kingbase用户
        pkill -9 -u kingbase 2>/dev/null
        sleep 1
        userdel -r kingbase 2>/dev/null
        if [ $? -ne 0 ]; then
            echo "警告: 无法完全删除用户kingbase，可能需要手动清理"
        fi
    fi
    
    # 删除邮件目录
    echo "删除邮件目录..."
    rm -rf /var/spool/mail/kingbase 2>/dev/null
    
    # 清理定时任务
    echo "清理定时任务..."
    crontab -u kingbase -r 2>/dev/null
    
    # 清理环境变量
    echo "清理环境变量..."
    sed -i '/# Kingbase Environment/,/alias sys_restore/d' /home/kingbase/.bashrc 2>/dev/null
    sed -i '/# Kingbase Environment/,/alias sys_restore/d' /home/kingbase/.bash_profile 2>/dev/null
    
    # 清理套接字文件和锁文件
    echo "清理套接字文件和锁文件..."
    rm -f /tmp/.s.KINGBASE.* 2>/dev/null
    rm -f /home/kingbase/kingbase_sockets/.s.KINGBASE.* 2>/dev/null
    rm -f /home/kingbase/tmp/.s.KINGBASE.* 2>/dev/null
    
    echo "卸载kingbase==ok"
}

##### 模式选择函数
select_mode() {
    while true; do
        echo "========================================"
        echo "请选择操作："
        echo "1. Oracle模式安装"
        echo "2. MySQL模式安装"
        echo "3. SQL Server模式安装"
        echo "4. PostgreSQL模式安装"
        echo "5. 卸载金仓数据库并删除所有相关目录"
        read -p "请输入选项 (1-5): " mode_choice
        
        case $mode_choice in
            1) 
                MODE="oracle"
                DBMODE="ORACLE"
                CASESENSITIVE="YES"
                break
                ;;
            2) 
                MODE="mysql"
                DBMODE="MYSQL"
                CASESENSITIVE="NO"  # MySQL模式大小写不敏感
                break
                ;;
            3) 
                MODE="sqlserver"
                DBMODE="SQLSERVER"
                CASESENSITIVE="NO"
                break
                ;;
            4) 
                MODE="pg"
                DBMODE="PG"
                CASESENSITIVE="YES"
                break
                ;;
            5)
                uninstall_kingbase
                # 卸载后继续显示菜单
                continue
                ;;
            *)
                echo "无效选择，请重新输入"
                sleep 1
                continue
                ;;
        esac
    done
    
    echo "已选择: $MODE 模式"
    
    # 根据模式调整备份路径
    DUMP_PATH="/home/kingbase/backup/dump_${MODE}"
    REPO_PATH="/home/kingbase/backup/rman_${MODE}"
}

##### 查找授权文件
find_license() {
    # 模式特定的授权文件
    mode_license="${MODE}_license.dat"
    # 通用授权文件
    tongyong_license="tongyong_license.dat"
    
    if [ -f "${WORKDIR}/${mode_license}" ]; then
        LICENSE="${WORKDIR}/${mode_license}"
        echo "使用模式特定授权文件: $LICENSE"
    elif [ -f "${WORKDIR}/${tongyong_license}" ]; then
        LICENSE="${WORKDIR}/${tongyong_license}"
        echo "使用通用授权文件: $LICENSE"
    else
        LICENSE=""
        echo "警告: 未找到授权文件"
    fi
}

##### Defind env
export LANG=C
loginfo(){
  echo -e "[$(date +'%Y-%m-%d %H:%M:%S')] $*"
}

# 主目录
WORKDIR=$(pwd)

# 备份开关 - 可在此处设置
LOGICAL_BACKUP="ON"  # ON 或 OFF
PHYSICAL_BACKUP="ON" # ON 或 OFF

# 检测是否已安装Kingbase
if check_kingbase_installed; then
    echo "已经安装kingbase数据库，重装请卸载"
    # 调用模式选择函数（包含卸载选项）
    select_mode
else
    # 未安装则直接选择模式
    select_mode
fi

# 调用授权文件查找函数
find_license

# 配置文件路径
conf_file=$(dirname $(readlink -f "$0"))"/kdb_install.conf"

# 如果配置文件存在，加载原有配置
if [ -f "$conf_file" ]; then
    for line in $(grep '^[a-zA-Z]' ${conf_file})
    do
        eval "export "$line
    done
else
    # 默认配置
    export KES_VERSION=V009R001
    export USER_NAME=kingbase
    export USER_HOME=${USER_HOME:-/home/${USER_NAME}}
    export USER_PASS=Admin123@Pl
    export INSTALL_DIR=/home/kingbase/ES/V${KES_VERSION:3:1}
    export PORTNO=54321
    export SYS=system
    export SYSPASSWD=123456
    export KGIS=NO
    export PS=NO
    export BACKUP_OPTION=11
    export KEEP_TIME=7
    export REPO_RETENTION_FULL_COUNT=2
fi

# 覆盖模式相关配置
export DBMODE=${DBMODE}
export CASESENSITIVE=${CASESENSITIVE}
export DUMP_PATH=${DUMP_PATH}
export REPO_PATH=${REPO_PATH}

SOFTPACKNAME=$(ls ${WORKDIR}/KingbaseES_${KES_VERSION:0:4}*.iso | awk -F '.' '{print $1}' 2>/dev/null)
GISNAME=$(ls ${WORKDIR}/postgis-*.gz 2>/dev/null)
silent_conf=/tmp/silent.conf
kingbase_conf=${INSTALL_DIR}/data/kingbase.conf
shared_mem=$(grep MemTotal /proc/meminfo | awk '{print $2/1024*0.25}' | awk -F'.' '{print $1}')
echo "[INFO] shared_mem: $shared_mem MB"
effective_mem=$(grep MemTotal /proc/meminfo | awk '{print $2/1024*0.5}' | awk -F'.' '{print $1}')
echo "[INFO] effective_mem: $effective_mem MB"
DATETIME=$(date +%Y%m%d)

##### Check env
checkEnv(){
if [ ! "$(whoami)" = "root" ]; then
  echo "[ERROR] Must run as user: root"
  exit 1
fi 

# 新增：检查/tmp空间
TMP_SPACE=$(df -k /tmp | awk 'NR==2 {print $4}')
if [ "$TMP_SPACE" -lt 1048576 ]; then # 小于1GB
    echo "[WARNING] /tmp 空间不足 (${TMP_SPACE}KB < 1GB)，尝试清理..."
    
    # 清理/tmp下7天未访问的文件
    find /tmp -type f -atime +7 -delete 2>/dev/null
    find /tmp -type d -empty -delete 2>/dev/null
    
    # 重新检查空间
    TMP_SPACE=$(df -k /tmp | awk 'NR==2 {print $4}')
    if [ "$TMP_SPACE" -lt 1048576 ]; then
        echo "[WARNING] 清理后/tmp空间仍不足，将使用/home/kingbase/tmp作为临时目录"
        mkdir -p /home/kingbase/tmp
        chown kingbase:kingbase /home/kingbase/tmp
        export TMPDIR=/home/kingbase/tmp
    fi
fi
ENVCHECK=""
if [ -x "/sbin/ifconfig" ] || [ -x "/usr/sbin/ifconfig" ]; then
  echo "[CONFIG_CHECK] ifconfig check passed."
else
   echo -e "[ERROR] ifconfig not exists,please yum install net-tools\n"
fi

if [ -x "/bin/unzip" ] || [ -x "/usr/bin/unzip" ]; then
  echo "[CONFIG_CHECK] unzip check passed."
else
   echo -e "[ERROR] unzip not exists.please yum install -y unzip.\n"
fi

if [ -x "/bin/tar" ] || [ -x "/usr/bin/tar" ]; then
  echo "[CONFIG_CHECK] tar check passed."
else
   echo -e "[ERROR] tar not exists,please yum install -y tar\n"
fi

if [ -x "/bin/timeout" ] || [ -x "/usr/bin/timeout" ]; then
  echo "[CONFIG_CHECK] timeout check passed."
else
   echo -e "[ERROR] timeout not exists. Installing it now...\n"
   yum install -y coreutils || apt-get install -y coreutils
   if [ $? -ne 0 ]; then
        echo "[WARNING] Failed to install timeout command, some operations may hang"
   fi
fi

if [ -z "$SOFTPACKNAME" ]; then
  ENVCHECK="${ENVCHECK} 1) ${WORKDIR}/KingbaseES*.iso not exists.\n"
  echo -e "[ERROR] ${WORKDIR}/KingbaseES*.iso not exists,please upload the file KingbaseES*.iso.\n"
  exit 1
fi

if [ -z "$GISNAME" ] && [ "$KGIS" = "YES" ]; then
  ENVCHECK="${ENVCHECK} 1) ${WORKDIR}/postgis*.gz not exists.\n"
  echo -e "[ERROR] ${WORKDIR}/postgis*.gz not exists,please upload the file postgis*.gz.\n"
  exit 1
fi

# 授权文件检查逻辑更新
if [ -z "$LICENSE" ]; then
  echo -e "[WARNING] No license file found. Installation will proceed without a license, please install it manually later.\n"
else
  echo "[INFO] Using license file: $LICENSE"
fi

# 检查安装路径是否存在
if [ -e "${INSTALL_DIR}" ]; then
    echo "The path ${INSTALL_DIR} exists. Please delete it first."
    exit 1
fi
}

optimizeSysctlConf() {
NUMMEM=$(awk '/^MemTotal:/{printf("%d\n",$2/1000)}' /proc/meminfo)
if [ -f /etc/systemd/logind.conf ]; then
    conf_exist=$(grep -c "kingbase" /etc/sysctl.conf)
    if [ "$conf_exist" -eq 0 ]; then
        echo "[INFO] optimize SysctlConf."
        cat >> /etc/sysctl.conf <<EOF

#add by kingbase
kernel.sem = 50100 64128000 50100 1280
vm.dirty_background_ratio=2
vm.dirty_ratio = 40	
vm.overcommit_memory = 2
vm.overcommit_ratio = 90
vm.swappiness = 1
fs.aio-max-nr = 1048576
fs.file-max = 6815744
fs.nr_open = 20480000
net.ipv4.ip_local_port_range = 10000 65000
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_max_tw_buckets = 6000
net.ipv4.tcp_max_syn_backlog = 65536
net.core.somaxconn=1024
net.core.netdev_max_backlog = 32768
net.core.wmem_default = 8388608
net.core.wmem_max = 1048576
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_syn_retries = 2
net.ipv4.route.gc_timeout = 100
net.ipv4.tcp_wmem = 8192 436600 873200
net.ipv4.tcp_rmem  = 32768 436600 873200
net.ipv4.tcp_mem = 94500000 91500000 92700000
net.ipv4.tcp_max_orphans = 3276800
EOF
        sysctl -p >/dev/null 2>&1
    else
        echo "[WARNING] sysctl is already optimized, so we do nothing"
    fi
fi
}

optimizeLimitConf(){
conf_exist=$(grep -c "kingbase" /etc/security/limits.conf)
if [ "$conf_exist" -eq 0 ]; then
    echo "[INFO] optimize limit configuration"
    cat >> /etc/security/limits.conf <<EOF

#add by kingbase
* soft nofile 655360
root soft nofile 655360
* hard nofile 655360
root hard nofile 655360
* soft nproc 655360
root soft nproc 655360
* hard nproc 655360
root hard nproc 655360
* soft core unlimited
root soft core unlimited
* hard core unlimited
root hard core unlimited
* soft memlock 50000000
root soft memlock 50000000
* hard memlock 50000000
root hard memlock 50000000

EOF
else
    echo "[WARNING] limit is already optimized, so we do nothing"
fi

# modify nproc.conf
if [ -f /etc/security/limits.d/90-nproc.conf ]; then
    conf_exist=$(grep -c "kingbase" /etc/security/limits.d/90-nproc.conf)
    if [ "$conf_exist" -eq 0 ]; then
        echo "[INFO] 90-nproc modifing" 
        cat >> /etc/security/limits.d/90-nproc.conf <<EOF
#kingbase
kingbase soft nproc 65536
EOF
    else
        echo "[INFO] 90-nproc already modified, so we do nothing" 
    fi
elif [ -f /etc/security/limits.d/20-nproc.conf ]; then
    conf_exist=$(grep -c "kingbase" /etc/security/limits.d/20-nproc.conf)
    if [ "$conf_exist" -eq 0 ]; then
        echo "[INFO] 20-nproc modifing" 
        cat >> /etc/security/limits.d/20-nproc.conf <<EOF
#kingbase
kingbase soft nproc 65536
EOF
    else
        echo "[WARNING] 20-nproc already modified, so we do nothing" 
    fi
fi
}

optimizeSelinux(){
if [ -f /etc/selinux/config ]; then
    conf_exist=$(grep -c "kingbase" /etc/selinux/config)
    if [ "$conf_exist" -eq 0 ]; then
        echo "[INFO] disable selinux"
        sed -i "s/^#SELINUX/#add by kingbase\nSELINUX/g" /etc/selinux/config
        sed -i "s/^SELINUX=enforcing/#add by kingbase\nSELINUX=disabled/g" /etc/selinux/config
        sed -i "s/^SELINUX=permissive/#add by kingbase\nSELINUX=disabled/g" /etc/selinux/config
        sed -i "s/^SELINUX=disabled/#add by kingbase\nSELINUX=disabled/g" /etc/selinux/config
        setenforce 0
        getenforce
    else
        echo "[WARNING] selinux is already disabled, so we do nothing"
    fi
fi
}

optimizeLogind(){
if [ -f /etc/systemd/logind.conf ]; then
    conf_exist=$(grep -c "kingbase" /etc/systemd/logind.conf)
    if [ "$conf_exist" -eq 0 ]; then
        echo "[INFO] disable selinux"
        sed -i "s/^#RemoveIPC/#add by kingbase\nRemoveIPC/g" /etc/systemd/logind.conf
        sed -i "s/^RemoveIPC=yes/#add by kingbase\nRemoveIPC=no/g" /etc/systemd/logind.conf
        sed -i "s/^RemoveIPC=no/#add by kingbase\nRemoveIPC=no/g" /etc/systemd/logind.conf
    else
        echo "[WARNING] RemoveIPC is already no, so we do nothing"
    fi
fi
}

optimizeScheduler(){
DISKSCH=$(lsblk -d | grep disk | head -n 1 | awk '{print $1}' | xargs -I {} cat /sys/block/{}/queue/scheduler | grep -c '\[deadline\]')
if [ "$DISKSCH" -eq 0 ]; then
    echo "[INFO] optimize disk scheduler."
    for list_blk in $(lsblk -d | grep disk | awk '{print $1}')
    do
        echo deadline > /sys/block/${list_blk}/queue/scheduler
    done
else
    echo "[WARNING] disk scheduler is already optimize, so we do nothing"
fi
}

stopfirewall(){
if systemctl is-active --quiet firewalld; then
    echo "[INFO] stop firewall"
    systemctl stop firewalld
    systemctl disable firewalld
else
    echo "[WARNING] firewall is already stop, so we do nothing"
fi
}

##### Create group and user
createUser(){
echo "[INFO] Creating group [${USER_NAME}] and user [${USER_NAME}] with HOME [$USER_HOME]."
UOS_TYPE=$(grep -ci uos /proc/version)
KYLIN_TYPE=$(grep -Eci 'kylin|ky10' /proc/version)
RHEL_TYPE=$(grep -ci 'Red Hat' /proc/version)
[ -f /etc/os-version ] && UOS_EULOR_TYPE=$(grep -c 'UnionTech OS Server' /etc/os-version) || UOS_EULOR_TYPE=0

if [ $RHEL_TYPE -ge 1 ] || [ $KYLIN_TYPE -ge 1 ] || [ $UOS_EULOR_TYPE -ge 1 ]; then
    if id "${USER_NAME}" &>/dev/null; then
        echo "[WARNING] User ${USER_NAME} already exists, skipping creation."
    else
        if ! useradd -d "${USER_HOME}" -m -s /bin/bash "${USER_NAME}" >/dev/null 2>&1; then
            echo "[ERROR] Failed to create user ${USER_NAME}"
            return 1
        else
            echo "[INFO] User [${USER_NAME}] created successfully."
        fi
        chage -M 99999 "${USER_NAME}" >/dev/null 2>&1
        echo "${USER_PASS}" | passwd --stdin "${USER_NAME}" >/dev/null 2>&1
    fi
elif [ $UOS_TYPE -ge 1 ]; then
    if id "${USER_NAME}" &>/dev/null; then
        echo "[WARNING] User ${USER_NAME} already exists, skipping creation."
    else
        if ! adduser --disabled-password --gecos "" "${USER_NAME}" --quiet >/dev/null 2>&1; then
            echo "[ERROR] Create user [${USER_NAME}] error,please deluser ${USER_NAME} and rm -rf ${USER_HOME}"
            exit 1
        fi
        echo "${USER_NAME}:${USER_PASS}" | chpasswd
    fi
else
    echo "[ERROR] OS is not in RHEL,UOS20,KYLIN,please check"
    exit 1
fi

# 确保家目录存在
if [ ! -d "${USER_HOME}" ]; then
    mkdir -p "${USER_HOME}"
    chown "${USER_NAME}:${USER_NAME}" "${USER_HOME}"
fi

# 创建套接字目录
mkdir -p "${USER_HOME}/kingbase_sockets"
chown "${USER_NAME}:${USER_NAME}" "${USER_HOME}/kingbase_sockets"
chmod 700 "${USER_HOME}/kingbase_sockets"
}

##### mount software and install
mount_iso(){
echo "[INFO] mount [${SOFTPACKNAME}.iso]."

# 创建挂载点
mkdir -p /mnt

# 如果已经挂载则先卸载
if mount | grep -q "/mnt.*iso"; then
    echo "[INFO] 检测到/mnt已被挂载，先卸载"
    umount /mnt 2>/dev/null
    sleep 1
fi

# 挂载ISO文件
if ! mount -o loop "${SOFTPACKNAME}.iso" /mnt 2>/dev/null; then
    echo "[ERROR] 挂载ISO文件失败: ${SOFTPACKNAME}.iso"
    echo "[DEBUG] 当前目录文件:"
    ls -la "${SOFTPACKNAME}.iso" 2>/dev/null || echo "ISO文件不存在"
    exit 1
fi

echo "[INFO] ISO文件挂载成功"

# 进入挂载目录
cd /mnt
echo "[INFO] 进入挂载目录: $(pwd)"

# 检查是否有setup.sh脚本
if [ -f "./setup.sh" ]; then
    INSTALL_TYPE="setup_sh"
    echo "[INFO] 发现setup.sh脚本"
else
    # 检查是否有install.jar
    if [ -f "./setup/install.jar" ]; then
        INSTALL_TYPE="jar"
        echo "[INFO] 发现install.jar文件"
    elif [ -x "./setup/install.bin" ]; then
        INSTALL_TYPE="bin"
        echo "[INFO] 发现install.bin文件"
    else
        echo "[ERROR] 未找到有效的安装文件"
        echo "[DEBUG] 当前目录结构:"
        find . -name "install.*" -o -name "setup.sh" 2>/dev/null
        umount /mnt 2>/dev/null
        exit 1
    fi
fi

echo "[INFO] 准备执行安装程序，类型: $INSTALL_TYPE"
}

### silent install KingbaseES V8R3
silent_install(){
mkdir -p "${INSTALL_DIR}/" 2>/dev/null
chown -R "${USER_NAME}:${USER_NAME}" "${INSTALL_DIR}" 2>/dev/null
chown -R "${USER_NAME}:${USER_NAME}" "${INSTALL_DIR}/../../" 2>/dev/null

# 如果有授权文件则复制
if [ -n "$LICENSE" ]; then
    cp "$LICENSE" /tmp/license.dat
    chown "${USER_NAME}:${USER_NAME}" /tmp/license.dat 2>/dev/null
    chmod 644 /tmp/license.dat 2>/dev/null
fi

# === 新增：确保有足够的临时空间 ===
TMP_NEEDED=1024 # 需要的最小空间(MB)
if [ -z "$TMPDIR" ]; then
    TMPDIR="/tmp"
fi

TMP_AVAIL=$(df -m "$TMPDIR" | awk 'NR==2 {print $4}')
if [ "$TMP_AVAIL" -lt "$TMP_NEEDED" ]; then
    echo "[WARNING] $TMPDIR 空间不足 (${TMP_AVAIL}MB < ${TMP_NEEDED}MB)，创建专用临时目录..."
    mkdir -p "${USER_HOME}/install_tmp"
    chown "${USER_NAME}:${USER_NAME}" "${USER_HOME}/install_tmp"
    export TMPDIR="${USER_HOME}/install_tmp"
    echo "[INFO] 使用临时目录: $TMPDIR"
fi

# 创建环境变量 - 确保PATH设置正确
cat >"${USER_HOME}/.bashrc" <<EOF
# Kingbase Environment
export PATH=${INSTALL_DIR}/Server/bin:\$PATH
export KINGBASE_HOME=${INSTALL_DIR}
export KINGBASE_DATA=${INSTALL_DIR}/data
export LD_LIBRARY_PATH=${INSTALL_DIR}/Server/lib:\$LD_LIBRARY_PATH

# 确保环境变量立即生效
export PATH
export LD_LIBRARY_PATH

alias ksql='${INSTALL_DIR}/Server/bin/ksql -U ${SYS} -d TEST -h /home/kingbase/kingbase_sockets'
alias sys_ctl='${INSTALL_DIR}/Server/bin/sys_ctl'
alias sys_dump='${INSTALL_DIR}/Server/bin/sys_dump'
alias sys_restore='${INSTALL_DIR}/Server/bin/sys_restore'

# 设置默认套接字目录
export PGHOST=/home/kingbase/kingbase_sockets

# 设置临时目录
export TMPDIR=${TMPDIR}
EOF

# 创建.bash_profile确保登录时加载环境变量
cat >"${USER_HOME}/.bash_profile" <<EOF
# 登录时加载.bashrc
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi

# 设置PS1提示符
export PS1='[\u@\h \W]\$ '
EOF

# 确保环境文件权限正确
chown "${USER_NAME}:${USER_NAME}" "${USER_HOME}/.bashrc" "${USER_HOME}/.bash_profile"
chmod 644 "${USER_HOME}/.bashrc" "${USER_HOME}/.bash_profile"

# 创建静默安装配置文件 (根据新格式)
cat >"$silent_conf" <<EOF
#KingbaseES V9

#choseInstallDir
INSTALL_PATH=${INSTALL_DIR}

#choseLisence
LICENSE_PATH=/tmp/license.dat

#choseTools,COMPONENTS=Server,Interface,KingbaseHA,DeployTool,KDTS,KStudio
COMPONENTS=Server,Interface,KingbaseHA,DeployTool,KDTS,KStudio

#shortcuts CREATE_SHORTCUT:yes or no; SHORTCUT_USER: 1:current user 2:all user; SHORTCUT_GROUP_NAME:name of program group
CREATE_SHORTCUT=yes
SHORTCUT_USER=1
SHORTCUT_GROUP_NAME=KingbaseES${KES_VERSION}

#Database config
DB_PORT=${PORTNO}
DB_USER=${SYS}
DB_PASSWORD=${SYSPASSWD}
DB_PASSWORD2=${SYSPASSWD}
ENCODING_PARAM=${ENCODING}
LOCALE_PARAM=${LOCALE_PARAM}
CASE_SENSITIVE_PARAM=${CASESENSITIVE}
BLOCK_SIZE_PARAM=${BLOCKSIZE}
DATABASE_MODE_PARAM=${DBMODE}
AUTHENTICATION_METHOD_PARAM=scram-sha-256
EOF

chown "${USER_NAME}:${USER_NAME}" "${silent_conf}" 2>/dev/null

echo "[INFO] 开始安装KingbaseES数据库..."
if [ "$INSTALL_TYPE" = "setup_sh" ]; then
    # 使用setup.sh脚本安装
    echo "[INFO] 使用setup.sh脚本安装方式"
    # 创建非root用户来执行安装
    # 先复制安装文件到用户目录
    cp -r /mnt/* ${USER_HOME}/
    chown -R "${USER_NAME}:${USER_NAME}" ${USER_HOME}/*
    
    # 使用setup.sh安装
    timeout 600 su - "${USER_NAME}" -c "cd ${USER_HOME} && ./setup.sh -i silent -f ${silent_conf} > ${USER_HOME}/install.log 2>&1"
elif [ "$INSTALL_TYPE" = "jar" ]; then
    # 新的install.jar安装方式
    echo "[INFO] 使用install.jar安装方式"
    timeout 600 su - "${USER_NAME}" -c "cd /mnt && java -jar ./setup/install.jar -options ${silent_conf} > ${USER_HOME}/install.log 2>&1"
elif [ "$INSTALL_TYPE" = "bin" ]; then
    # 传统install.bin安装方式
    echo "[INFO] 使用install.bin安装方式"
    timeout 600 su - "${USER_NAME}" -c "cd /mnt/setup && ./install.bin -silent -f ${silent_conf} > ${USER_HOME}/install.log 2>&1"
else
    echo "[ERROR] 未知的安装类型: $INSTALL_TYPE"
    exit 1
fi

if [ $? -ne 0 ]; then
    if [ $? -eq 124 ]; then
        echo "[WARNING] 数据库安装超时，但可能已完成，继续后续步骤"
        tail -20 ${USER_HOME}/install.log
    else
        echo "[ERROR] 数据库安装失败，请查看日志: ${USER_HOME}/install.log"
        exit 1
    fi
else
    echo "[INFO] 数据库安装成功"
fi

# === 修复：检查并初始化数据目录 ===
if [ ! -d "${INSTALL_DIR}/data" ] || [ ! -f "${INSTALL_DIR}/data/kingbase.conf" ]; then
    echo "[WARNING] 数据目录未正确初始化，执行手动初始化..."
    
    # 清理可能存在的旧数据
    rm -rf "${INSTALL_DIR}/data" 2>/dev/null
    mkdir -p "${INSTALL_DIR}/data"
    chown "${USER_NAME}:${USER_NAME}" "${INSTALL_DIR}/data"
    
    # 构建初始化命令
    INIT_CMD="${INSTALL_DIR}/Server/bin/initdb -D ${INSTALL_DIR}/data -U ${SYS} --locale=C --lc-collate=C -E UTF8 --pwfile=/tmp/kingbase_password"
    
    # MySQL模式特殊处理
    if [ "$DBMODE" = "MYSQL" ]; then
        INIT_CMD="${INIT_CMD} --enable-mysql-compatible"
        echo "[INFO] 为MySQL模式添加兼容性参数"
    fi
    
    # 创建密码文件
    echo "${SYSPASSWD}" > /tmp/kingbase_password
    chown "${USER_NAME}:${USER_NAME}" /tmp/kingbase_password
    
    # 执行初始化
    echo "执行初始化命令: $INIT_CMD"
    timeout 300 su - "${USER_NAME}" -c "source ~/.bashrc && $INIT_CMD"
    
    # 清理密码文件
    rm -f /tmp/kingbase_password
    
    if [ $? -ne 0 ]; then
        echo "[ERROR] 手动初始化数据目录失败"
        exit 1
    else
        echo "[INFO] 手动初始化数据目录成功"
        
        # 创建 kingbase.auto.conf 文件
        cat > "${INSTALL_DIR}/data/kingbase.auto.conf" <<EOF
# Automatically generated during installation
include 'kingbase.conf'
EOF
        chown "${USER_NAME}:${USER_NAME}" "${INSTALL_DIR}/data/kingbase.auto.conf"
    fi
fi

if [ "$KGIS" = "YES" ]; then
    echo "[INFO] 安装PostGIS扩展..."
    timeout 300 tar -zxf "${GISNAME}" --strip-components=1 -C "${INSTALL_DIR}/Server"
    if [ $? -ne 0 ]; then
        echo "[WARNING] PostGIS扩展安装失败或超时，但继续后续步骤"
    else
        chown -R "${USER_NAME}:${USER_NAME}" "${INSTALL_DIR}" 2>/dev/null
    fi
fi

# 创建数据库配置文件
cat >"${INSTALL_DIR}/data/kingbase.conf" <<EOF
listen_addresses='*'
max_connections=1000
port = ${PORTNO}
shared_buffers = ${shared_mem}MB
effective_cache_size = ${effective_mem}MB
work_mem =10MB
maintenance_work_mem=1GB
max_locks_per_transaction=1024
max_wal_size=64GB
checkpoint_timeout=20min
checkpoint_completion_target=0.9
wal_level=replica
archive_mode=on
archive_command=''
logging_collector=on
log_destination='stderr'
log_directory='sys_log'
log_filename='kingbase-%d.log'
log_truncate_on_rotation=on
log_rotation_age=1440
log_statement='ddl'
log_checkpoints=on
log_lock_waits=on
log_autovacuum_min_duration=0
log_temp_files=0
lc_messages='C'
log_min_duration_statement=1000
log_line_prefix='%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h'
vacuum_cost_limit=2000
control_file_copy = '${USER_HOME}/control_file.bak'
# 使用用户空间套接字目录避免权限问题
unix_socket_directories = '${USER_HOME}/kingbase_sockets'
EOF

# 对于R003版本的特殊配置
if [ "${KES_VERSION:4}" = "R003" ]; then
    echo "char_default_type='char'" >> "${INSTALL_DIR}/data/kingbase.conf"
fi

# kgis配置
if [ "$KGIS" = "YES" ]; then
    if [ "${KES_VERSION:4}" = "R003" ]; then
        cat >>"${INSTALL_DIR}/data/kingbase.conf" <<EOF
ora_plsql_style = off
ora_func_style = off
ora_input_emptystr_isnull = off
char_default_type = 'char'
EOF
    else
        cat >>"${INSTALL_DIR}/data/kingbase.conf" <<EOF
nls_length_semantics=char
enable_upper_colname=false
ora_numop_style=false
ora_input_emptystr_isnull=off
EOF
    fi
fi

# 启动数据库
echo "[INFO] 启动数据库..."

# 确保套接字目录权限正确
chmod 750 "${USER_HOME}/kingbase_sockets"
chown "${USER_NAME}:${USER_NAME}" "${USER_HOME}/kingbase_sockets"

# 清理旧的套接字文件和锁文件
echo "[INFO] 清理旧的套接字文件和锁文件..."
rm -f /tmp/.s.KINGBASE.${PORTNO}.lock 2>/dev/null
rm -f /tmp/.s.KINGBASE.*.lock 2>/dev/null
rm -f /tmp/.s.KINGBASE.${PORTNO} 2>/dev/null
rm -f /tmp/.s.KINGBASE.* 2>/dev/null
rm -f ${USER_HOME}/kingbase_sockets/.s.KINGBASE.* 2>/dev/null

echo "[INFO] 启动数据库服务..."
timeout 300 su - "${USER_NAME}" -c "source ~/.bashrc && ${INSTALL_DIR}/Server/bin/sys_ctl start -D ${INSTALL_DIR}/data > ${USER_HOME}/db_start.log 2>&1"

if [ $? -ne 0 ]; then
    if [ $? -eq 124 ]; then
        echo "[WARNING] 数据库启动超时，尝试强制清理..."
    else
        echo "[WARNING] 数据库启动失败，尝试强制清理..."
    fi
    
    # 强制清理
    pkill -9 -f "bin/kingbase" 2>/dev/null
    rm -f /tmp/.s.KINGBASE.* 2>/dev/null
    rm -f ${USER_HOME}/kingbase_sockets/.s.KINGBASE.* 2>/dev/null
    
    echo "再次尝试启动数据库..."
    timeout 300 su - "${USER_NAME}" -c "source ~/.bashrc && ${INSTALL_DIR}/Server/bin/sys_ctl start -D ${INSTALL_DIR}/data >> ${USER_HOME}/db_start.log 2>&1"
    
    if [ $? -ne 0 ]; then
        echo "[WARNING] 数据库仍然启动失败，但继续后续步骤"
        echo "最后10行日志："
        tail -10 ${USER_HOME}/db_start.log
        echo "请检查日志文件: ${USER_HOME}/db_start.log"
    else
        echo "[INFO] 数据库启动成功"
    fi
else
    echo "[INFO] 数据库启动成功"
fi

# 检查数据库进程
KESPROCESS=$(pgrep -f 'bin/kingbase' | wc -l)
if [ "$KESPROCESS" -ge 1 ]; then
    echo "[INFO] 数据库已成功启动"
    if [ "${KES_VERSION:4}" != "R003" ]; then
        echo "[INFO] 访问命令: su - kingbase -c \"source ~/.bashrc && ksql -U system -W '${SYSPASSWD}' -d test\""
    else
        echo "[INFO] 访问命令: su - kingbase -c \"source ~/.bashrc && ksql -U SYSTEM -W '${SYSPASSWD}' -d TEST\""
    fi
else
    echo "[WARNING] 数据库进程未运行，但继续后续步骤"
fi

# 检查套接字文件是否生成
echo "检查套接字文件..."
sleep 5
if [ -S "${USER_HOME}/kingbase_sockets/.s.KINGBASE.${PORTNO}" ]; then
    echo "套接字文件已生成: ${USER_HOME}/kingbase_sockets/.s.KINGBASE.${PORTNO}"
else
    echo "警告: 套接字文件未生成，请检查数据库日志: ${USER_HOME}/db_start.log"
fi
}

initkgis(){
if [ "$KGIS" != "YES" ]; then
    return 0
fi

export gisdb=gisdata

echo "[INFO] 初始化PostGIS扩展..."
timeout 600 su - "${USER_NAME}" <<ENDTAG
source ~/.bashrc
export PGPASSWORD=${SYSPASSWD}
export KINGBASE_PASSWORD=${SYSPASSWD}

${INSTALL_DIR}/Server/bin/sys_ctl -D ${INSTALL_DIR}/data -w restart;
${INSTALL_DIR}/Server/bin/createdb -p${PORTNO} ${gisdb}

${INSTALL_DIR}/Server/bin/ksql -p${PORTNO} ${gisdb} <<EOF
create user sde superuser;
create schema sde;
alter schema sde owner to sde;
alter user sde password 'Admin@9000';
create user rds_superuser superuser;
alter user rds_superuser password 'Admin@9000';
EOF

if [ "${KES_VERSION:4}" = "R003" ]; then
    ${INSTALL_DIR}/Server/bin/createdb -p${PORTNO} postgres
    ${INSTALL_DIR}/Server/bin/ksql -p${PORTNO} postgres <<EOF
\set SQLTERM /
CREATE OR REPLACE INTERNAL FUNCTION sys_catalog.pg_has_role(NAME, TEXT) RETURNS BOOLEAN LANGUAGE SQL STABLE AS \$function\$ SELECT sys_catalog.SYS_HAS_ROLE(\$1,\$2)\$function\$;
/
CREATE OR REPLACE INTERNAL FUNCTION sys_catalog.PG_TRY_ADVISORY_LOCK(INT8) RETURNS bool LANGUAGE SQL STABLE AS \$function\$ SELECT sys_catalog.SYS_TRY_ADVISORY_LOCK(\$1)\$function\$;
/
CREATE OR REPLACE INTERNAL FUNCTION sys_catalog.PG_ADVISORY_UNLOCK_ALL() RETURNS VOID LANGUAGE SQL STABLE AS \$function\$ SELECT sys_catalog.SYS_ADVISORY_UNLOCK_ALL()\$function\$;
/
\set SQLTERM ;
\c ${gisdb}
create extension postgis;
create extension postgis_sfcgal;
create extension postgis_topology;
create extension address_standardizer;
create extension address_standardizer_data_us;
alter language plsql rename to plpgsql;
grant USAGE on SCHEMA pg_catalog to sde;
grant SELECT on ALL tables in schema pg_catalog to sde;
\set SQLTERM /
CREATE OR REPLACE INTERNAL FUNCTION sys_catalog.pg_has_role(NAME, TEXT) RETURNS BOOLEAN LANGUAGE SQL STABLE AS \$function\$ SELECT sys_catalog.SYS_HAS_ROLE(\$1,\$2)\$function\$;
/
CREATE OR REPLACE INTERNAL FUNCTION sys_catalog.PG_TRY_ADVISORY_LOCK(INT8) RETURNS bool LANGUAGE SQL STABLE AS \$function\$ SELECT sys_catalog.SYS_TRY_ADVISORY_LOCK(\$1)\$function\$;
/
CREATE OR REPLACE INTERNAL FUNCTION sys_catalog.PG_ADVISORY_UNLOCK_ALL() RETURns VOID LANGUAGE SQL STABLE AS \$function\$ SELECT sys_catalog.SYS_ADVISORY_UNLOCK_ALL()\$function\$;
/
\set SQLTERM ;
EOF
else
    ${INSTALL_DIR}/Server/bin/ksql -p${PORTNO} ${gisdb} <<EOF
create extension postgis;
create extension postgis_raster;
create extension postgis_sfcgal;
create extension fuzzystrmatch;
create extension postgis_tiger_geocoder;
set exclude_reserved_words = 'level';
create extension postgis_topology;
create extension address_standardizer;
create extension address_standardizer_data_us;
alter system set allow_system_table_dml=on;
select sys_reload_conf();
select sys_sleep(1);
update pg_proc set proisstrict=false where proname ilike '%addgeo%' and proargtypes='1043 1043 1043 1043 23 1043 23 16';
alter system set allow_system_table_dml=off;
select sys_reload_conf();
EOF
fi

${INSTALL_DIR}/Server/bin/ksql -p${PORTNO} ${gisdb} <<EOF
CREATE TABLE global_points (
id SERIAL PRIMARY KEY,
name VARCHAR(64),
location GEOGRAPHY(POINT,4326)
);
INSERT INTO global_points (name, location) VALUES ('Town', ST_GeographyFromText('SRID=4326;POINT(-110 30)') );
select * from global_points;
EOF

ENDTAG

if [ $? -eq 124 ]; then
    echo "[WARNING] PostGIS扩展初始化超时，但继续后续步骤"
else
    echo "[INFO] PostGIS扩展初始化完成"
fi
}

startup_with_powerup(){
chmod a+x /etc/rc.local
rc_local_exist=$(grep -c "${INSTALL_DIR}/data" /etc/rc.local)
if [ "$rc_local_exist" -eq 0 ]; then
    cat >> /etc/rc.local <<EOF
su - ${USER_NAME} -c "source ~/.bashrc && ${INSTALL_DIR}/Server/bin/sys_ctl start -D ${INSTALL_DIR}/data" 2>/dev/null
EOF
    echo "[INFO] 已添加开机自启动"
else
    echo "rc.local is already exists ${INSTALL_DIR},nothing to do "
fi
}

logical_backup(){
echo "[INFO] 配置逻辑备份..."
echo "${USER_NAME}" >>/etc/cron.allow
if [ $? -ne 0 ]; then
    echo "[ERROR] Failed to add cron.allow"
    exit 3
fi

crontab_exist=$(su - "${USER_NAME}" -c "crontab -l" | grep -c backup8)
if [ "$crontab_exist" -gt 1 ]; then
    echo "logical_backup is exist,so we do nothing"
    return 1
fi

# 备份和修改配置
su - "${USER_NAME}" -c "cp ${INSTALL_DIR}/SupTools/suptools.ini ${INSTALL_DIR}/SupTools/suptools_${DATETIME}.ini"
sed -i "s|^HOME_PATH\s*=\s*.*|HOME_PATH=${INSTALL_DIR}/Server|" "${INSTALL_DIR}/SupTools/suptools.ini"
sed -i "s|^BIN_PATH\s*=\s*.*|BIN_PATH=${INSTALL_DIR}/Server/bin|" "${INSTALL_DIR}/SupTools/suptools.ini"
sed -i "s|^LD_LIBRARY_PATH\s*=\s*.*|LD_LIBRARY_PATH=${INSTALL_DIR}/Server/lib:\$LD_LIBRARY_PATH|" "${INSTALL_DIR}/SupTools/suptools.ini"
sed -i "s|^USER\s*=\s*.*|USER=${SYS}|" "${INSTALL_DIR}/SupTools/suptools.ini"
sed -i "s|^PORT\s*=\s*.*|PORT=${PORTNO}|" "${INSTALL_DIR}/SupTools/suptools.ini"
sed -i "s|^PASSWORD\s*=\s*.*|PASSWORD=${SYSPASSWD}|" "${INSTALL_DIR}/SupTools/suptools.ini"
sed -i "s|^DUMP_PATH\s*=\s*.*|DUMP_PATH=${DUMP_PATH}|" "${INSTALL_DIR}/SupTools/suptools.ini"
sed -i "s|^KEEP_TIME\s*=\s*.*|KEEP_TIME=${KEEP_TIME}|" "${INSTALL_DIR}/SupTools/suptools.ini"

cat >>"${INSTALL_DIR}/SupTools/kb_backup/backup8.conf" <<EOF
kdb_list=\`\${kdb_bin}/ksql -p \${kdb_port} -U \${kdb_user}  -c "SELECT datname FROM pg_database where datname not in ('template1','template0','security');" template1 |head -n -2|tail -n +3\`
EOF

# 检查sys_hba.conf文件是否存在，如果不存在则等待或创建
if [ ! -f "${INSTALL_DIR}/data/sys_hba.conf" ]; then
    echo "[WARNING] sys_hba.conf 文件不存在，等待数据库初始化完成..."
    sleep 10
    
    # 如果仍然不存在，则尝试从模板创建
    if [ ! -f "${INSTALL_DIR}/data/sys_hba.conf" ] && [ -f "${INSTALL_DIR}/data/pg_hba.conf" ]; then
        cp "${INSTALL_DIR}/data/pg_hba.conf" "${INSTALL_DIR}/data/sys_hba.conf"
        chown "${USER_NAME}:${USER_NAME}" "${INSTALL_DIR}/data/sys_hba.conf"
    elif [ ! -f "${INSTALL_DIR}/data/sys_hba.conf" ]; then
        echo "[ERROR] sys_hba.conf 文件不存在，无法配置逻辑备份"
        return 1
    fi
fi

su - "${USER_NAME}" -c "cp ${INSTALL_DIR}/data/sys_hba.conf ${INSTALL_DIR}/data/sys_hba_${DATETIME}.conf"
sed -i '/^local\s\+all\s\+all\s\+/s/scram-sha-256/trust/'  "${INSTALL_DIR}/data/sys_hba.conf"
sed -i '/^host\s\+all\s\+all\s\+127.0.0.1\/32\s\+/s/scram-sha-256/trust/'  "${INSTALL_DIR}/data/sys_hba.conf"
su - "${USER_NAME}" -c "${INSTALL_DIR}/Server/bin/sys_ctl reload -D ${INSTALL_DIR}/data >/dev/null 2>&1"

echo "[INFO] 测试逻辑备份..."
timeout 300 su - "${USER_NAME}" -c "bash ${INSTALL_DIR}/SupTools/kb_backup/fast_deploy_backup8.sh > ${USER_HOME}/logical_backup_test.log 2>&1"
if [ $? -ne 0 ]; then
    if [ $? -eq 124 ]; then
        echo "[WARNING] 逻辑备份测试超时，但继续后续步骤"
    else
        echo "[WARNING] 逻辑备份测试失败，但继续后续步骤"
    fi
fi

crontab_exist=$(su - "${USER_NAME}" -c "crontab -l" | grep -c backup8)
if [ "$crontab_exist" -eq 1 ]; then
    echo "[INFO] 逻辑备份配置成功"
else
    echo "[WARNING] 未添加逻辑备份定时任务"
fi
}

rman_backup(){
echo "[INFO] 开始物理备份配置: ${REPO_PATH}"

# 检查并清理旧备份目录
if [ -d "${REPO_PATH}" ]; then
    echo "[WARNING] 备份目录已存在: ${REPO_PATH}, 清理中..."
    rm -rf "${REPO_PATH}"
    # 确保目录被删除
    sleep 1
    if [ -d "${REPO_PATH}" ]; then
        echo "[ERROR] 无法删除目录 ${REPO_PATH}，请手动检查"
        return 1
    fi
fi

# 创建新备份目录
mkdir -p "${REPO_PATH}"
chown -R "${USER_NAME}:${USER_NAME}" "${REPO_PATH}"
echo "[INFO] 创建备份目录: ${REPO_PATH}"

# 创建日志目录并授权
echo "[INFO] 创建日志目录: ${INSTALL_DIR}/Server/log"
mkdir -p "${INSTALL_DIR}/Server/log"
chown -R "${USER_NAME}:${USER_NAME}" "${INSTALL_DIR}/Server/log"

# 检查端口冲突
port=8890
result=$(lsof -i :$port)
if [ -z "$result" ]; then
    echo "[INFO] 端口 $port 可用"
else
    echo "[WARNING] 端口 $port 被占用:"
    echo "$result"
    # 强制终止占用进程
    echo "强制终止占用进程..."
    pkill -9 -f "sys_securecmdd"
    sleep 2
fi

# 启动安全守护进程
echo "[INFO] 启动安全守护进程..."
timeout 60 ${INSTALL_DIR}/Server/bin/sys_HAscmdd.sh init && \
timeout 60 ${INSTALL_DIR}/Server/bin/sys_HAscmdd.sh start >/dev/null 2>&1
if [ $? -ne 0 ]; then
    echo "[WARNING] 安全守护进程启动失败，但继续后续步骤"
fi

# 准备备份配置
if [ -f "${INSTALL_DIR}/Server/share/sys_backup.conf" ]; then
    su - "${USER_NAME}" -c "cp ${INSTALL_DIR}/Server/share/sys_backup.conf ${INSTALL_DIR}/Server/bin/sys_backup.conf"
fi

cat >"${INSTALL_DIR}/Server/bin/sys_backup.conf" <<EOF
_target_db_style=single 
_one_db_ip=127.0.0.1
_repo_ip=127.0.0.1 
_stanza_name=${USER_NAME} 
_os_user_name=${USER_NAME} 
_repo_path=${REPO_PATH} 
_repo_retention_full_count=${REPO_RETENTION_FULL_COUNT} 
_single_data_dir=${INSTALL_DIR}/data 
_single_bin_dir=${INSTALL_DIR}/Server/bin 
_single_db_user=${SYS} 
_single_db_port=${PORTNO} 
_use_scmd=on 
_start_fast=y 
_compress_type=gz 
EOF

# 修复sys_backup.sh脚本
echo "[INFO] 修复sys_backup.sh脚本..."
sed -i 's/echo -E/echo/g' ${INSTALL_DIR}/Server/bin/sys_backup.sh

# 执行备份初始化
echo "[INFO] 初始化物理备份...(详细日志: ${INSTALL_DIR}/Server/log/backup_init.log)"
start_time=$(date +%s)
timeout 600 su - "${USER_NAME}" -c "source ~/.bashrc && ${INSTALL_DIR}/Server/bin/sys_backup.sh init > ${INSTALL_DIR}/Server/log/backup_init.log 2>&1"

if [ $? -ne 0 ]; then
    if [ $? -eq 124 ]; then
        echo "[WARNING] 物理备份初始化超时，但继续后续步骤"
    else
        echo "[WARNING] 物理备份初始化失败，但继续后续步骤"
    fi
    echo "=== 最后10行日志 ==="
    tail -10 ${INSTALL_DIR}/Server/log/backup_init.log
    echo "===================="
else
    end_time=$(date +%s)
    echo "[INFO] 初始化完成，耗时 $((end_time - start_time)) 秒"
fi

echo "[INFO] 启动物理备份服务...(详细日志: ${INSTALL_DIR}/Server/log/backup_start.log)"
timeout 300 su - "${USER_NAME}" -c "source ~/.bashrc && ${INSTALL_DIR}/Server/bin/sys_backup.sh start > ${INSTALL_DIR}/Server/log/backup_start.log 2>&1"

if [ $? -ne 0 ]; then
    if [ $? -eq 124 ]; then
        echo "[WARNING] 物理备份服务启动超时，但继续后续步骤"
    else
        echo "[WARNING] 物理备份服务启动失败，但继续后续步骤"
    fi
    echo "=== 最后10行日志 ==="
    tail -10 ${INSTALL_DIR}/Server/log/backup_start.log
    echo "===================="
fi

# 添加定时任务
crontab_exist=$(su - "${USER_NAME}" -c "crontab -l" | grep -c rman)
if [ "$crontab_exist" -gt 0 ]; then
    echo "[INFO] 物理备份定时任务已存在"
else
    echo "[INFO] 添加物理备份定时任务"
    su - "${USER_NAME}" -c "(crontab -l; echo '0 2 * * * ${INSTALL_DIR}/Server/bin/sys_backup.sh backup >/dev/null 2>&1') | crontab -"
    if [ $? -eq 0 ]; then
        echo "[INFO] 物理备份定时任务添加成功"
    else
        echo "[WARNING] 添加物理备份定时任务失败"
    fi
fi
}

test_db_connection() {
    echo "[INFO] 测试数据库连接..."
    sleep 10  # 给数据库更多启动时间
    
    # 使用绝对路径和PGPASSWORD环境变量传递密码，设置300秒超时
    timeout 300 su - "${USER_NAME}" -c "source ~/.bashrc && \
        PGPASSWORD='${SYSPASSWD}' ${INSTALL_DIR}/Server/bin/ksql \
        -h /home/kingbase/kingbase_sockets \
        -U ${SYS} \
        -d test \
        -c 'SELECT version();' > ${USER_HOME}/connection_test.log 2>&1"
    
    local result=$?
    if [ $result -eq 0 ]; then
        echo "[SUCCESS] 数据库连接测试成功"
        echo "数据库版本信息:"
        cat ${USER_HOME}/connection_test.log
        return 0
    else
        if [ $result -eq 124 ]; then
            echo "[WARNING] 数据库连接测试超时（300秒），跳过此步骤"
        else
            echo "[WARNING] 数据库连接测试失败，跳过此步骤"
            echo "错误日志:"
            cat ${USER_HOME}/connection_test.log
        fi
        return 0  # 返回0表示跳过此错误
    fi
}

KES_installinfo(){
# 获取数据库版本
if [ -x "${INSTALL_DIR}/Server/bin/kingbase" ]; then
    KES_VERSION_STR=$(${INSTALL_DIR}/Server/bin/kingbase --version)
else
    KES_VERSION_STR="未知版本"
fi

# 获取网络信息
KINGBASE_IP_ADDR=$(hostname -I | awk '{print $1}')
KINGBASE_MAC_ADDR=$(ip link | awk '/ether/ {print $2; exit}')

# 获取授权信息
LICENSE_INFO=""
if [ -n "$LICENSE" ]; then
    LICENSE_INFO="授权文件: $LICENSE"
    if [ -x "${INSTALL_DIR}/Server/bin/ksql" ]; then
        timeout 60 su - "${USER_NAME}" -c "PGPASSWORD='${SYSPASSWD}' ${INSTALL_DIR}/Server/bin/ksql -h /home/kingbase/kingbase_sockets -U system -d test -c 'select get_license_validdays();' -t | head -1" > /tmp/license_days.txt
        if [ $? -eq 0 ]; then
            KES_LICENSE=$(cat /tmp/license_days.txt)
            LICENSE_INFO="${LICENSE_INFO}\n授权有效期: ${KES_LICENSE}天"
        else
            LICENSE_INFO="${LICENSE_INFO}\n[警告] 无法获取授权有效期"
        fi
        rm -f /tmp/license_days.txt
    else
        LICENSE_INFO="${LICENSE_INFO}\n[警告] 无法获取授权有效期"
    fi
else
    LICENSE_INFO="[警告] 未找到有效的授权文件"
fi

# 获取定时任务
crontab_content=$(timeout 30 su - "${USER_NAME}" -c "crontab -l" 2>/dev/null)
if [ -z "$crontab_content" ]; then
    crontab_content="无定时备份任务"
fi

# 备份开关状态
BACKUP_STATUS="逻辑备份: $LOGICAL_BACKUP\n物理备份: $PHYSICAL_BACKUP"

# 创建安装报告
REPORT_FILE="${WORKDIR}/KES安装目录清单_${MODE}_${DATETIME}.txt"

# 获取更详细的版本信息
DETAILED_VERSION=$(timeout 60 su - "${USER_NAME}" -c "source ~/.bashrc && PGPASSWORD='${SYSPASSWD}' ${INSTALL_DIR}/Server/bin/ksql -h /home/kingbase/kingbase_sockets -U system -d test -c 'SELECT version();'" 2>/dev/null)

cat >"${REPORT_FILE}" <<EOF
========================================
KES 安装目录清单：${KES_VERSION_STR}
========================================
----> Kingbase 安装目录绝对路径：${INSTALL_DIR}
----> Kingbase 数据目录绝对路径：${INSTALL_DIR}/data 
----> Kingbase 数据模式： ${MODE}  
----> Kingbase 数据库大小写敏感：${CASESENSITIVE}
----> Kingbase 数据库授权: ${LICENSE_INFO}

========================================
KES 用户密码：
========================================
----> Kingbase 超级管理员用户名：${SYS}
----> Kingbase 超级管理员密码：${SYSPASSWD}
----> Kingbase 使用ksql登入：
------------> 切换至 Kingbase 用户：su - kingbase 
------------> 执行命令登入ksql工具：source ~/.bashrc && ksql -U system -W '${SYSPASSWD}' -d test
------------> 或者直接使用完整路径：${INSTALL_DIR}/Server/bin/ksql -h /home/kingbase/kingbase_sockets -U system -W '${SYSPASSWD}' -d test

========================================
KES 连接相关信息：
========================================
----> Kingbase 服务器IP 地址：${KINGBASE_IP_ADDR}
----> Kingbase 服务器MAC地址：${KINGBASE_MAC_ADDR}
----> Kingbase 实例端口：${PORTNO}
----> Kingbase 开发JDBC连接串：
---------------> jdbc:Kingbase8://${KINGBASE_IP_ADDR}:${PORTNO}/数据库名

========================================
运维方式：
========================================
----> 对于 Kingbase 所有运维操作都需要切换到 Kingbase 用户执行：
------------> 切换至 Kingbase 用户：su - kingbase 
-------------------> 查看 Kingbase 数据库进程 ：ps axu|grep kingbase 
-------------------> 启动 Kingbase 数据库 ：source ~/.bashrc && sys_ctl start   -D     ${INSTALL_DIR}/data 
-------------------> 停止 Kingbase 数据库 ：source ~/.bashrc && sys_ctl stop    -D     ${INSTALL_DIR}/data 
-------------------> 重启 Kingbase 数据库 ：source ~/.bashrc && sys_ctl restart -D     ${INSTALL_DIR}/data 
-------------------> 生效 Kingbase 数据库 ：source ~/.bashrc && sys_ctl reload  -D     ${INSTALL_DIR}/data 
-------------------> 或者使用完整路径：${INSTALL_DIR}/Server/bin/sys_ctl [start|stop|restart|reload] -D ${INSTALL_DIR}/data

========================================
定时自动备份任务：
========================================
${crontab_content}

========================================
备份路径：
========================================
--逻辑备份路径:${DUMP_PATH}
--物理备份路径:${REPO_PATH}

========================================
详细版本信息：
========================================
${DETAILED_VERSION}

========================================
安装报告生成时间：$(date)
========================================
EOF

# 显示安装报告
echo -e "\n===================== 安装完成 ======================"
cat "${REPORT_FILE}"
echo "======================================================"
echo "安装报告已保存至: ${REPORT_FILE}"
}

### 主执行流程
# 创建备份目录
mkdir -p "${DUMP_PATH}" "${REPO_PATH}"
chown -R "${USER_NAME}:${USER_NAME}" "${DUMP_PATH}" "${REPO_PATH}" 2>/dev/null

# 执行安装流程
checkEnv
optimizeSysctlConf
optimizeLimitConf
optimizeSelinux
optimizeLogind
optimizeScheduler
stopfirewall
createUser
mount_iso
silent_install
initkgis
startup_with_powerup

# 测试数据库连接（即使失败也继续）
test_db_connection

# 根据备份选项执行备份
if [ "$BACKUP_OPTION" = "11" ]; then
    echo "逻辑和物理备份都开启"
    
    if [ "$LOGICAL_BACKUP" = "ON" ]; then
        echo "[INFO] 开始配置逻辑备份..."
        logical_backup
    else
        echo "[INFO] 逻辑备份开关关闭，跳过"
    fi
    
    if [ "$PHYSICAL_BACKUP" = "ON" ]; then
        echo "[INFO] 开始配置物理备份..."
        rman_backup
    else
        echo "[INFO] 物理备份开关关闭，跳过"
    fi
elif [ "$BACKUP_OPTION" = "10" ]; then
    if [ "$LOGICAL_BACKUP" = "ON" ]; then
        logical_backup
    else
        echo "[INFO] 逻辑备份开关关闭，跳过"
    fi
elif [ "$BACKUP_OPTION" = "01" ]; then
    if [ "$PHYSICAL_BACKUP" = "ON" ]; then
        rman_backup
    else
        echo "[INFO] 物理备份开关关闭，跳过"
    fi
fi

# 生成安装报告
KES_installinfo